<script setup lang="ts">
import { computed, onMounted, reactive, ref, unref } from 'vue'
import { Close, Edit, Plus, Refresh, Search } from '@element-plus/icons-vue'
import draggable from 'vuedraggable'
import { ElMessage } from 'element-plus'
import { useRoute } from 'vue-router'
import { useBaseApi } from '@/api/base'
import { clone, findTree } from 'xe-utils'
import { defaultColumns } from '@/utils/custom'
import type {
  BusinessUIColumnType,
  BusinessUITableType,
  IFListColumnType,
  IFListType
} from '@/types/custom'

import CustomColumnForm from '@/views/system/business/custom/components/CustomColumnForm.vue'
import CustomGridGroup from '@/views/system/business/custom/components/CustomGridGroup.vue'

const { GetBusinessUI, GetIFList, SaveBusinessUI, GetBusinessTree } = useBaseApi()

const route = useRoute()

const scrollRef = ref()
const columnFormRef = ref()
const gridGroupRef = ref()
const params = reactive<BusinessUITableType>({
  id: '',
  api: '',
  method: '',
  type_name: '',
  default_value: '',
  default_value_parse: {
    toolbarConfig: {
      enabled: true,
      custom: true,
      export: true
    }
  },
  pagination: false,
  edit_render: false,
  querys: [],
  columns: [],
  children: []
})
// { id: '', business_id: '', default_value: '', default_value_parse: {} }
const loading = ref(false)
const keywords = ref('')
const list = ref<IFListType[]>([])
const checked = ref<string>('')
const columns = computed(() => {
  const listItem = list.value.find((f) => f.type_name === checked.value)
  return listItem ? listItem.column : []
})
const tableColumns = ref<BusinessUIColumnType[]>([])
const checkedColumn = ref('')
const businessItems = ref<RouteItems>([])

const loopColumns = computed(() => {
  const search = (keywords.value || '').toLowerCase().trim()
  if (search) {
    return columns.value.filter(
      (f) =>
        f.name.toLowerCase().indexOf(search) !== -1 ||
        f.data_type.toLowerCase().indexOf(search) !== -1
    )
  } else {
    return columns.value
  }
})

const businessName = computed(() => {
  const item = findTree(unref(businessItems), (f) => f.id === params.id)
  return item && item.item ? item.item.meta.title : ''
})

/**
 * 保存UI
 */
const saveData = () => {
  params.columns = unref(tableColumns.value)
  params.type_name = checked.value
  if (params.columns.some((s) => s.is_pid)) {
    if (!params.columns.some((s) => s.set_json_parse.props.treeNode)) {
      ElMessage.warning('开启树形列表后，需要设置一个列拓展属性 "treeNode" 为 "true"')
      return
    }
  }
  loading.value = true
  SaveBusinessUI(params)
    .then(() => {
      ElMessage.success('保存成功')
    })
    .finally(() => (loading.value = false))
}

/**
 * 查询
 */
const onFetch = () => {
  loading.value = true
  GetBusinessUI(params.id)
    .then(({ data }) => {
      if (!data.default_value_parse.toolbarConfig) {
        data.default_value_parse.toolbarConfig = {
          enabled: true,
          custom: true,
          export: true,
          zoom: true
        }
      }
      tableColumns.value = data.columns
      params.api = data.api
      params.method = data.method
      params.querys = data.querys
      params.columns = data.columns
      params.children = data.children || []
      params.default_value = data.default_value
      params.default_value_parse = data.default_value_parse
      params.pagination = data.pagination
      params.edit_render = data.edit_render
      if (data.type_name) checked.value = data.type_name
    })
    .finally(() => (loading.value = false))
}

/**
 * 查询可选字段
 */
const onFetchIFList = () => {
  GetIFList().then(({ data }) => {
    list.value = data
    if (data.length && !checked.value) {
      checked.value = data[0].type_name
    }
    if (params.id) onFetch()
  })
}

/**
 * 是否已选
 * @param column
 */
const isActive = (column: IFListColumnType) => {
  return tableColumns.value.some((s) => s.field === column.name)
}

/**
 * 添加到表格列
 * @param column
 */
const addTableColumn = (column: IFListColumnType) => {
  const item = clone(
    defaultColumns.find((f) => f.field === column.name),
    true
  )
  tableColumns.value.push({
    field: column.name,
    title: item ? item.title : '',
    set_json: '',
    set_json_parse: {
      props: item?.props ? item.props : { width: '100' },
      nodeApp: item ? item.nodeApp : undefined,
      formatType: item ? item.formatType : undefined
    },
    is_pid: false,
    is_sort_col: false,
    customer: {
      actions: []
    }
  })
}

/**
 * 新增空字段
 */
const addEmptyColumn = () => {
  tableColumns.value.push({
    field: `empty_${Date.now()}`,
    title: '',
    set_json: '',
    set_json_parse: { props: { width: '60' } },
    is_pid: false,
    is_sort_col: false,
    customer: {
      actions: []
    }
  })
}

/**
 * 已选表格选中的列
 * @param column
 */
const onActiveChange = (column: BusinessUIColumnType) => {
  checkedColumn.value = column.field
  columnFormRef.value.open(column, checked.value)
}

/**
 * 删除
 * @param index
 */
const removeColumn = (index: number) => {
  tableColumns.value.splice(index, 1)
}

/**
 * 查询业务
 */
const onFetchBusiness = () => {
  GetBusinessTree().then(({ data }) => {
    businessItems.value = data
  })
}

onMounted(() => {
  params.id = String(route.query.id || '')
  onFetchIFList()
  onFetchBusiness()
})
</script>

<template>
  <div class="system-dept-container layout-padding">
    <el-row :gutter="5" class="h100">
      <el-col :xs="24" :sm="6" :md="6" :lg="4" :xl="4" class="flex flex-column mb5">
        <el-card shadow="hover" class="h100">
          <div class="h100 flex flex-column">
            <el-select v-model="checked" class="mb10 w100" filterable>
              <el-option
                v-for="(item, index) in list"
                :key="index"
                :value="item.type_name"
                :label="item.name"
              />
            </el-select>
            <div v-if="!columns.length">
              <el-skeleton />
              <el-skeleton />
              <el-skeleton />
            </div>
            <div class="flex-grow" style="position: relative; min-height: 200px">
              <el-input
                v-model="keywords"
                placeholder="关键字"
                :suffix-icon="Search"
                clearable
                class="mb5"
              />
              <el-scrollbar style="position: absolute">
                <div class="list-group">
                  <div
                    v-for="item in loopColumns"
                    :key="item.name"
                    class="list-group-item flex flex-shrink justify-between"
                    :class="{ active: isActive(item) }"
                  >
                    <div class="flex align-center">
                      <el-text>{{ item.name }}</el-text>
                    </div>
                    <el-button
                      :icon="Plus"
                      size="small"
                      circle
                      :disabled="isActive(item)"
                      @click="addTableColumn(item)"
                    />
                  </div>
                  <div class="list-group-item flex flex-shrink justify-between">
                    <div class="flex align-center">
                      <el-text>占位</el-text>
                    </div>
                    <el-button :icon="Plus" size="small" circle @click="addEmptyColumn" />
                  </div>
                  <div style="height: 50px; width: 100%"></div>
                </div>
              </el-scrollbar>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="18" :md="18" :lg="20" :xl="20" class="h100 mb5">
        <el-scrollbar>
          <el-card shadow="hover" class="mb5">
            <div class="flex align-center">
              <span>{{ $t(businessName) }}</span>
              <el-space :size="5" class="ml-auto">
                <!-- <el-tree-select
                v-model="params.id"
                filterable
                default-expand-all
                :data="businessItems"
                value-key="id"
                placeholder="选择业务"
                @change="onFetch"
                :props="{
                  label: 'title'
                }"
                style="width: 240px"
              /> -->
                <el-input v-model="params.api" placeholder="接口地址" style="width: 300px" />
                <el-select
                  v-model="params.method"
                  class="flex-shrink"
                  placeholder="请求方式"
                  clearable
                  style="width: 100px"
                >
                  <el-option label="GET" value="get" />
                  <el-option label="POST" value="post" />
                  <el-option label="PUT" value="put" />
                  <el-option label="DELETE" value="delete" />
                </el-select>
                <el-button :icon="Refresh" @click="onFetch" :loading="loading" class="ml-auto">
                  刷新
                </el-button>
                <el-button type="primary" :icon="Edit" @click="saveData" :loading="loading">
                  保存UI配置
                </el-button>
              </el-space>
            </div>
          </el-card>
          <el-card shadow="hover" class="mb5" body-class="px10 py5">
            <el-space :size="5" class="flex align-center">
              <el-switch
                size="default"
                v-model="params.pagination"
                inline-prompt
                active-text="开启分页"
                inactive-text="开启分页"
              />
              <el-input
                v-model="params.default_value_parse.keyField"
                placeholder="表格主键（默认：id）"
              ></el-input>
              <el-input
                v-model="params.default_value_parse.emptyText"
                placeholder="无数据提示信息（默认：暂无数据）"
                style="width: 200px"
              ></el-input>
            </el-space>
            <el-space :size="5" class="flex align-center">
              <el-switch
                size="default"
                v-model="params.edit_render"
                inline-prompt
                active-text="开启行内编辑"
                inactive-text="开启行内编辑"
              />
              <el-select
                v-if="params.edit_render"
                v-model="params.default_value_parse.renderMethod"
                placeholder="渲染方式"
                clearable
                style="width: 330px"
              >
                <el-option label="触发渲染（单击触发）" value="editRender" />
                <!-- <el-option label="直接渲染（树形等复杂的组件不支持，数据量大性能极差。）" value="cellRender" /> -->
              </el-select>
              <span v-if="params.edit_render" class="color-warning font12">
                注：开启后需要配置form表单配置，且只支持基础组件，下拉，日期，输入框，开关等。
              </span>
            </el-space>
            <el-space class="flex align-center">
              <el-switch
                size="default"
                v-model="params.default_value_parse.toolbarConfig.enabled"
                inline-prompt
                active-text="开启表格工具栏"
                inactive-text="开启表格工具栏"
              />
              <div
                class="d-flex align-center"
                v-if="params.default_value_parse.toolbarConfig.enabled"
              >
                <el-checkbox v-model="params.default_value_parse.toolbarConfig.custom"
                  >列配置按钮
                </el-checkbox>
                <el-checkbox v-model="params.default_value_parse.toolbarConfig.export"
                  >导出按钮
                </el-checkbox>
                <el-checkbox v-model="params.default_value_parse.toolbarConfig.print"
                  >打印按钮
                </el-checkbox>
                <!--            <el-checkbox v-model="params.default_value_parse.toolbarConfig.zoom"-->
                <!--            >全屏模式按钮-->
                <!--            </el-checkbox>-->
                <!--            <el-checkbox v-model="params.default_value_parse.toolbarConfig.refresh"-->
                <!--            >刷新按钮-->
                <!--            </el-checkbox>-->
              </div>
            </el-space>
          </el-card>
          <el-card shadow="hover" class="mb5" body-class="pb1">
            <el-scrollbar ref="scrollRef" always class="pb10">
              <draggable
                v-model="tableColumns"
                group="column"
                item-key="name"
                :animation="300"
                class="table-group flex pb1"
              >
                <template #item="{ element, index }">
                  <div
                    class="table-group-item flex-shrink flex align-center justify-between"
                    :class="{ active: element.field === checkedColumn }"
                    @click="onActiveChange(element)"
                  >
                    <span>{{ element.title || element.field }}</span>
                    <el-button
                      :icon="Close"
                      size="small"
                      circle
                      text
                      type="danger"
                      class="ml5"
                      @click.stop="removeColumn(index)"
                    />
                  </div>
                </template>
                <template #footer v-if="!tableColumns.length">
                  <div class="flex align-center justify-center color-warning">在左侧添加字段</div>
                </template>
              </draggable>
            </el-scrollbar>
          </el-card>
          <el-card shadow="hover" class="mb5">
            <CustomColumnForm ref="columnFormRef" />
          </el-card>
          <el-card shadow="hover" class="mb5">
            <CustomGridGroup
              v-model="params.children"
              :business-items="businessItems"
              v-model:height="params.default_value_parse.height"
              ref="gridGroupRef"
            />
          </el-card>
        </el-scrollbar>
      </el-col>
    </el-row>
  </div>
</template>

<style scoped lang="scss">
.table-group {
  list-style: none;
  min-height: 30px;
  min-width: 100%;

  .table-group-item {
    position: relative;
    padding: 2px 10px;
    margin-bottom: -1px;
    border: 1px solid var(--el-border-color);
    cursor: move;
    user-select: none;
    margin-right: 3px;
    border-radius: 3px;
    min-width: 100px;

    &.active {
      color: var(--el-color-primary);
      border-color: var(--el-color-primary);
    }
  }
}

.list-group {
  list-style: none;

  .list-group-item {
    position: relative;
    padding: 5px;
    margin-bottom: -1px;
    border: 1px solid var(--el-border-color);
    user-select: none;

    &.active {
      cursor: no-drop;
      opacity: 0.4;
    }
  }

  .list-group-item:first-child {
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
  }
}
</style>
